home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
shells
/
bashsrc.zoo
/
bashline.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-05
|
19KB
|
708 lines
/* bashline.c -- Bash's interface to the readline library. */
/* Copyright (C) 1989 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <readline/readline.h>
#include "config.h"
#include "general.h"
#include "variables.h"
#include "builtins.h"
#include "quit.h"
/* Called once from parse.y if we are going to use readline. */
initialize_readline ()
{
char **attempt_shell_completion (), *bash_tilde_expand ();
int shell_expand_line (), insert_last_arg (), bash_symbolic_link_hook ();
char *get_string_value ();
rl_terminal_name = get_string_value ("TERM");
rl_instream = stdin, rl_outstream = stderr;
rl_special_prefixes = "$@%";
/* Bind up our special shell functions. */
rl_add_defun ("shell-expand-line", shell_expand_line, META(CTRL('E')));
rl_add_defun ("insert-last-argument", insert_last_arg, META('.'));
rl_add_defun ("insert-last-argument", insert_last_arg, META('_'));
/* Tell the completer that we want a crack first. */
rl_attempted_completion_function = (Function *)attempt_shell_completion;
/* Tell the tilde expander that we want a crack if it fails. */
rl_tilde_expander = (Function *)bash_tilde_expand;
/* Tell the completer that we might want to follow symbolic links. */
rl_symbolic_link_hook = (Function *)bash_symbolic_link_hook;
/* And don't forget to allow conditional parsing of the ~/.inputrc
file. */
rl_readline_name = "Bash";
}
/* Contains the line to push into readline. */
char *push_to_readline = (char *)NULL;
/* Push the contents of push_to_readline into the
readline buffer. */
bash_push_line ()
{
if (push_to_readline)
{
rl_insert_text (push_to_readline);
free (push_to_readline);
push_to_readline = (char *)NULL;
}
}
/* Call this to set the initial text for the next line to read
from readline. */
bash_re_edit (line)
char *line;
{
if (push_to_readline)
free (push_to_readline);
push_to_readline = savestring (line);
rl_startup_hook = bash_push_line;
}
/* **************************************************************** */
/* */
/* Readline Stuff */
/* */
/* **************************************************************** */
/* If the user requests hostname completion, then simply build a list
of hosts, and complete from that forever more. */
#ifndef ETCHOSTS
#define ETCHOSTS "/etc/hosts"
#endif
/* The kept list of hostnames. */
static char **hostname_list = (char **)NULL;
/* The physical size of the above list. */
static int hostname_list_size = 0;
/* The length of the above list. */
static int hostname_list_length = 0;
/* Whether or not HOSTNAME_LIST has been initialized. */
int hostname_list_initialized = 0;
/* Non-zero means that HOSTNAME_LIST needs to be sorted. */
static int hostname_list_needs_sorting = 0;
/* Initialize the hostname completion table. */
initialize_hostname_list ()
{
char *temp = get_string_value ("hostname_completion_file");
if (!temp)
temp = ETCHOSTS;
snarf_hosts_from_file (temp);
sort_hostname_list ();
if (hostname_list)
hostname_list_initialized++;
}
/* Add NAME to the list of hosts. */
add_host_name (name)
char *name;
{
if (hostname_list_length + 2 > hostname_list_size)
{
if (!hostname_list)
hostname_list = (char **)xmalloc (sizeof (char *));
hostname_list = (char **)
xrealloc (hostname_list,
(1 + (hostname_list_size += 100)) * sizeof (char *));
}
hostname_list[hostname_list_length] = savestring (name);
hostname_list[++hostname_list_length] = (char *)NULL;
hostname_list_needs_sorting++;
}
/* After you have added some names, you should sort the list of names. */
sort_hostname_list ()
{
extern int qsort_string_compare ();
if (hostname_list_needs_sorting && hostname_list)
qsort (hostname_list, hostname_list_length,
sizeof (char *), qsort_string_compare);
hostname_list_needs_sorting = 0;
}
#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
snarf_hosts_from_file (filename)
char *filename;
{
FILE *file = fopen (filename, "r");
char *temp, buffer[256], name[256];
register int i, start;
if (!file)
return;
while (temp = fgets (buffer, 255, file))
{
/* Skip to first character. */
for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++);
/* If comment, ignore. */
if (buffer[i] == '#')
continue;
/* Skip internet address. */
for (; buffer[i] && !cr_whitespace (buffer[i]); i++);
/* Gobble up names. Each name is separated with whitespace. */
while (buffer[i] && buffer[i] != '#')
{
for (; i && cr_whitespace (buffer[i]); i++);
if (buffer[i] == '#')
continue;
for (start = i; buffer[i] && !cr_whitespace (buffer[i]); i++);
if ((i - start) == 0)
continue;
strncpy (name, buffer + start, i - start);
name[i - start] = '\0';
add_host_name (name);
}
}
fclose (file);
}
/* Return a NULL terminated list of hostnames which begin with TEXT.
Initialize the hostname list the first time if neccessary.
The array is malloc ()'ed, but not the individual strings. */
char **
hostnames_matching (text)
char *text;
{
register int i, len = strlen (text);
register int begin, end;
int last_search = -1;
char **result = (char **)NULL;
if (!hostname_list_initialized)
{
initialize_hostname_list ();
if (!hostname_list_initialized)
return ((char **)NULL);
}
sort_hostname_list ();
/* The list is sorted. Do a binary search on it for the first character
in TEXT, and then grovel the names of interest. */
begin = 0; end = hostname_list_length;
/* Special case. If TEXT consists of nothing, then the whole list is
what is desired. */
if (!*text)
{
result = (char **)xmalloc ((1 + hostname_list_length) * sizeof (char *));
for (i = 0; i < hostname_list_length; i++)
result[i] = hostname_list[i];
result[i] = (char *)NULL;
return (result);
}
/* Scan until found, or failure. */
while (end != begin)
{
int r;
i = ((end - begin) / 2) + begin;
if (i == last_search)
break;
if (hostname_list[i] &&
(r = strncmp (hostname_list[i], text, len)) == 0)
{
while (strncmp (hostname_list[i], text, len) == 0 && i) i--;
if (strncmp (hostname_list[i], text, len) != 0) i++;
begin = i;
while (hostname_list[i] &&
strncmp (hostname_list[i], text, len) == 0) i++;
end = i;
result = (char **)xmalloc ((1 + (end - begin)) * sizeof (char *));
for (i = 0; i + begin < end; i++)
result[i] = hostname_list[begin + i];
result[i] = (char *)NULL;
return (result);
}
last_search = i;
if (r < 0)
begin = i;
else
end = i;
}
return ((char **)NULL);
}
/* This is a ksh-style insert-last-arg function. The difference is that bash
puts stuff into the history file before expansion and file name generation,
so we deal with exactly what the user typed. Those wanting the other
behavior, at least for the last arg, can use `$_'. This also `knows' about
how rl_yank_nth_arg treats `$'. */
insert_last_arg(count, c)
int count, c;
{
extern int rl_explicit_arg;
if